const fs = require('fs')

const data = require('./幻栈.json').root

function walkTree(callback, root, path = '') {
  // 遍历树

  callback(root, path)
  if (root.children) {
    root.children.forEach((child) => {
      walkTree(callback, child, path + '/' + root.data.text)
    })
  }
}

function searchNode(content, isContainsNote) {
  // 查询节点，全匹配

  walkTree((node, path) => {
    if (
      node.data.text.toLowerCase() === content.toLowerCase() ||
      (isContainsNote && node.data.note?.toLowerCase() === content.toLowerCase())
    ) {
      console.log(path + '/' + node.data.text)
    }
  }, data)
}

function logWithBorder(text) {
  if (!Array.isArray(text)) {
    text = [text]
  }
  const maxLength = 100
  const topBottomBorder = '+'.padEnd(maxLength + 2, '-') + '+'

  console.log(topBottomBorder)
  text.forEach((line) => {
    console.log(line)
  })
}

function fuzzySearchNode(content, isContainsNote) {
  // 查询节点，模糊匹配

  walkTree((node, path) => {
    if (
      node.data.text.toLowerCase().includes(content.toLowerCase()) ||
      (isContainsNote && node.data.note?.toLowerCase().includes(content.toLowerCase()))
    ) {
      logWithBorder([path + '/' + node.data.text, node.data.note || '无描述'])
    }
  }, data)
}

function fuzzySearchNode2(content, isContainsNote) {
  traverseTree(
    data,
    (node, options) => {
      if (
        node.data.text.toLowerCase().includes(content.toLowerCase()) ||
        (isContainsNote && node.data.note?.toLowerCase().includes(content.toLowerCase()))
      ) {
        console.log(options.pathIds.join('/'))
      }
    },
    {includeParent: true, idKey: 'data.text'}
  )
}

function checkRepeatNode() {
  // 查询重复节点

  let occurrences = {}
  let result = {}

  walkTree((node, path) => {
    if (node.children.length !== 0) {
      return
    }

    let credential = occurrences[node.data.text.toLowerCase()]
    if (credential) {
      credential.count += 1
      credential.paths.push(path)
    } else {
      occurrences[node.data.text.toLowerCase()] = {
        count: 1,
        paths: [path]
      }
    }
  }, data)

  Object.keys(occurrences).forEach((key) => {
    if (occurrences[key].count > 1) {
      result[key] = occurrences[key]
    }
  })

  fs.writeFileSync('analysis.json', JSON.stringify(result))

  return result
}

function flatNodeContent(isNoNote, isSimpleFormat) {
  // 扁平化节点内容

  let result = []

  walkTree((node, path) => {
    if (node.children.length !== 0) {
      // 跳过非叶子节点
      return
    }

    if (isNoNote && node.data.note) {
      return
    }

    result.push({
      path: path,
      text: node.data.text,
      note: node.data.note
    })
  }, data)

  console.log(result.length)

  if (isSimpleFormat) {
    let resultText = ''
    result.forEach((item) => {
      resultText += `${item.text}\r\n`
    })
    fs.writeFileSync('library.txt', resultText)
  } else {
    fs.writeFileSync('library.json', JSON.stringify(result))
  }
}

/**
 * 通用树形结构遍历函数（优化子节点获取逻辑）
 * @param {Array|Object} tree 树形结构数据，可以是单节点对象或节点数组
 * @param {Function} callback 处理每个节点的回调函数，返回false可终止遍历
 * @param {Object} options 配置选项
 * @param {string|Function} [options.childrenKey='children'] 子节点属性标识，支持链式路径如'data.nodes'或函数
 * @param {Function|null} [options.getChildNodes=null] 自定义获取子节点的函数，优先级高于childrenKey
 * @param {string} [options.traversalType='depth'] 遍历类型: 'depth' 深度优先, 'breadth' 广度优先
 * @param {boolean} [options.includeParent=false] 是否在回调中包含父节点信息
 * @param {boolean} [options.postOrder=false] 深度优先时是否后序遍历(仅对depth有效)
 * @param {boolean} [options.includePath=true] 是否包含从根到当前节点的完整路径
 * @param {string|Function} [options.idKey='id'] 节点唯一标识字段，支持链式路径如'data.text'或函数
 */
function traverseTree(tree, callback, options = {}) {
  // 默认配置
  const {
    childrenKey = 'children',
    getChildNodes = null,
    traversalType = 'depth',
    includeParent = false,
    postOrder = false,
    includePath = true,
    idKey = 'id'
  } = options

  // 确保tree是数组，统一处理方式
  const nodes = Array.isArray(tree) ? tree : [tree]

  // 验证回调函数
  if (typeof callback !== 'function') {
    throw new Error('回调函数必须提供')
  }

  // 解析属性值的通用函数
  const getPropertyValue = (node, key) => {
    if (typeof key === 'function') {
      return key(node)
    }

    if (key.includes('.')) {
      const keys = key.split('.')
      let value = node

      for (const k of keys) {
        if (value === null || value === undefined) {
          return undefined
        }
        value = value[k]
      }
      return value
    }

    return node[key]
  }

  // 获取子节点的函数
  const getChildren = (node) => {
    if (typeof getChildNodes === 'function') {
      const result = getChildNodes(node)
      return Array.isArray(result) ? result : null
    }

    const value = getPropertyValue(node, childrenKey)
    return Array.isArray(value) ? value : null
  }

  // 获取节点ID
  const getNodeId = (node) => {
    return getPropertyValue(node, idKey)
  }

  // 深度优先遍历函数
  function dfs(node, parent, level, path, postOrder, includeParent, includePath) {
    const currentPath = [...path, node]
    const children = getChildren(node)
    const hasChildren = !!children?.length

    // 非后序遍历：先处理当前节点
    if (!postOrder) {
      const shouldContinue = callback(node, {
        parent: includeParent ? parent : null,
        level,
        isLeaf: !hasChildren,
        path: includePath ? currentPath : null,
        pathIds: includePath ? currentPath.map(getNodeId) : null
      })

      if (shouldContinue === false) {
        return false
      }
    }

    // 处理子节点
    if (hasChildren && children) {
      for (const child of children) {
        const shouldContinue = dfs(child, node, level + 1, currentPath, postOrder, includeParent, includePath)
        if (!shouldContinue) {
          return false
        }
      }
    }

    // 后序遍历：在处理完所有子节点后处理当前节点
    if (postOrder) {
      const shouldContinue = callback(node, {
        parent: includeParent ? parent : null,
        level,
        isLeaf: !hasChildren,
        path: includePath ? currentPath : null,
        pathIds: includePath ? currentPath.map(getNodeId) : null
      })

      if (shouldContinue === false) {
        return false
      }
    }

    return true
  }

  // 广度优先遍历处理
  function processBreadthFirst() {
    const queue = []

    nodes.forEach((node) => {
      const path = [node]
      queue.push({
        node,
        parent: null,
        level: 0,
        path
      })
    })

    while (queue.length > 0) {
      const {node, parent, level, path} = queue.shift()
      const children = getChildren(node)
      const hasChildren = !!children?.length

      const shouldContinue = callback(node, {
        parent: includeParent ? parent : null,
        level,
        isLeaf: !hasChildren,
        path: includePath ? path : null,
        pathIds: includePath ? path.map(getNodeId) : null
      })

      if (shouldContinue === false) {
        break
      }

      if (hasChildren && children) {
        children.forEach((child) => {
          const childPath = [...path, child]
          queue.push({
            node: child,
            parent: node,
            level: level + 1,
            path: childPath
          })
        })
      }
    }
  }

  // 根据遍历类型选择处理方式
  if (traversalType === 'depth') {
    // 遍历所有根节点
    for (const node of nodes) {
      const shouldContinue = dfs(node, null, 0, [], postOrder, includeParent, includePath)
      if (!shouldContinue) {
        break
      }
    }
  } else if (traversalType === 'breadth') {
    processBreadthFirst()
  } else {
    throw new Error('不支持的遍历类型，可选值: depth, breadth')
  }
}

// 2024/07/14
// checkRepeatNode()

// flatNodeContent(false, false)
// searchNode('lit')
fuzzySearchNode2('json-diff', true)
